package com.lordjoe.sudoku;

/**
 * com.lordjoe.sudoku.SudokuSolution
 * partial or complete solution may be constructed from an array of 81 ints ot a string
 * 'of 81 characters 0..9. NOTE 0 says unassigned
 * User: Steve
 * Date: 4/7/12
 */
public class SudokuSolution
{
    public static final SudokuSolution[] EMPTY_ARRAY = {};
    private Integer[] m_Values = new Integer[SudokuBoard.getBoardSize() * SudokuBoard.getBoardSize()];

    // puzzles from http://mapleta.maths.uwa.edu.au/~gordon/sudokupat.php
    //
    public static final String[] PUZZLES = {
            "790000300000006900800030076000005002005418700400700000610090008002300000009000054", // easy        http://www.sudoku.ws/easy-1.htm
            "300704280000060000050000730540003090009080600060900025036000070000070000072806004", // easy        http://www.sudoku.ws/easy-17.htm
            // Puzzles in the group X-Shape
            "400080006080000030009000200000503000700020008000809000001000700030000090500060004",   //
            //  17 hint
            "000000010400000000020000000000050407008000300001090000300400200050100000000806000",

    };

    public static final int[] VALUES_2_BY_2 =
            {
                    1, 0, 0, 0,
                    0, 3, 0, 2,
                    2, 0, 0, 4,
                    0, 4, 0, 1,

            };
    public static final int[] VALUES_2_BY_2X =
            {
                    1, 0, 4, 0,
                    0, 3, 0, 2,
                    2, 0, 3, 4,
                    0, 4, 0, 1,

            };
    // this is supposed to fail
    public static final int[] VALUES_2_BY_2_BAD =
            {
                    1, 0, 4, 0,
                    0, 3, 0, 2,
                    3, 0, 3, 4,
                    0, 4, 0, 1,

            };
  // this is supposed to fail
     public static final int[] VALUES1_BAD =
            {
                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 4, 0, 0, 0,
                    0, 0, 7, 0, 0, 0, 0, 0, 8,
                    6, 0, 0, 0, 0, 0, 9, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 6, 0, 3, 0, 0, 0, 0,
                    5, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 2,
                    0, 0, 0, 0, 0, 1, 0, 0, 0,

            };
    public static final int[] VALUESBOXES_BAD =
            {
                    0, 0, 0, 4, 0, 0, 0, 0, 0,
                    0, 7, 0, 0, 0, 4, 8, 0, 0,
                    0, 0, 7, 0, 0, 0, 0, 0, 8,
                    6, 0, 0, 3, 0, 0, 9, 0, 0,
                    0, 0, 6, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 3, 0, 0, 0, 9,
                    5, 0, 0, 0, 0, 1, 2, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 2,
                    0, 0, 5, 0, 0, 1, 0, 0, 0,

            };

    // http://www.websudoku.com/?level=1&set_id=1161660674
    public static final int[] VALUES1 =
            {
                    0, 0, 0, 8, 0, 1, 6, 0, 4,
                    6, 0, 4, 7, 0, 0, 0, 5, 0,
                    0, 5, 0, 9, 0, 6, 0, 0, 0,
                    7, 0, 0, 0, 9, 8, 0, 0, 2,
                    0, 3, 9, 0, 6, 0, 5, 8, 0,
                    5, 0, 0, 2, 1, 0, 0, 0, 7,
                    0, 0, 0, 1, 0, 4, 0, 3, 0,
                    0, 7, 0, 0, 0, 5, 1, 0, 9,
                    1, 0, 8, 3, 0, 9, 0, 0, 0,

            };

    public static final int[] VALUES1X =
            {
                    0, 0, 0, 7, 0, 0, 0, 0, 0,
                    5, 0, 0, 0, 0, 4, 9, 0, 2,
                    0, 0, 7, 1, 0, 0, 0, 5, 8,
                    6, 0, 0, 4, 1, 2, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 5, 3, 7, 0, 0, 4,
                    8, 6, 0, 0, 0, 1, 4, 0, 0,
                    7, 0, 1, 8, 0, 0, 0, 0, 3,
                    0, 0, 0, 0, 0, 5, 0, 0, 0,

            };

    public static final int[] VALUES2 =
            {
                    0, 0, 0, 7, 0, 0, 0, 0, 0,
                    5, 0, 0, 0, 0, 4, 9, 0, 2,
                    0, 0, 7, 1, 0, 0, 0, 5, 8,
                    6, 0, 0, 4, 1, 2, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 5, 3, 7, 0, 0, 4,
                    8, 6, 0, 0, 0, 1, 4, 0, 0,
                    7, 0, 1, 8, 0, 0, 0, 0, 3,
                    0, 0, 0, 0, 0, 5, 0, 0, 0

            };

    public static final String HARD_1 = "000000010400000000020000000000050407008000300001090000300400200050100000000806000";

    public static final SudokuSolution SOLN1_BAD = new SudokuSolution(VALUES1_BAD);
    public static final SudokuSolution SOLN1 = new SudokuSolution(VALUES1);
    public static final SudokuSolution SOLN2 = new SudokuSolution(VALUES2);

    public static int[] stringToInts(String s)
    {
        int[] ret = new int[s.length()];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = Integer.parseInt(s.substring(i, i + 1));

        }

        return ret;
    }

    public SudokuSolution()
    {

    }

    public SudokuSolution(String s)
    {
        this(stringToInts(s));
    }

    public SudokuSolution(int[] values)
    {
        int offset = 0;
        for (int col = 0; col < SudokuBoard.getBoardSize(); col++) {
            for (int row = 0; row < SudokuBoard.getBoardSize(); row++) {
                setValue(col, row, values[offset++]);
            }

        }

    }

    /**
     * are all 81 values specified
     * @return
     */
    public boolean isComplete()
    {
        for (int i = 0; i < m_Values.length; i++) {
            if (m_Values[i] == null)
                return false; // at least one unknown
        }
        return true;
    }

    public Integer getValue(int col, int row)
    {
        return m_Values[getIndex(col, row)];
    }

    public void setValue(int col, int row, int v)
    {
        if (v == 0)
            m_Values[getIndex(col, row)] = null;
        else
            m_Values[getIndex(col, row)] = v;
    }

    protected int getIndex(int col, int row)
    {
        return col * SudokuBoard.getBoardSize() + row;
    }

}
